home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 3.iso / dist / fw_apache.idb / usr / freeware / apache / include / ap_hook.h.z / ap_hook.h
C/C++ Source or Header  |  2001-01-10  |  26KB  |  711 lines

  1. #if 0
  2. =cut
  3. #endif
  4. /* ====================================================================
  5.  * Copyright (c) 1998-2000 The Apache Group.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer. 
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. All advertising materials mentioning features or use of this
  20.  *    software must display the following acknowledgment:
  21.  *    "This product includes software developed by the Apache Group
  22.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  23.  *
  24.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  25.  *    endorse or promote products derived from this software without
  26.  *    prior written permission. For written permission, please contact
  27.  *    apache@apache.org.
  28.  *
  29.  * 5. Products derived from this software may not be called "Apache"
  30.  *    nor may "Apache" appear in their names without prior written
  31.  *    permission of the Apache Group.
  32.  *
  33.  * 6. Redistributions of any form whatsoever must retain the following
  34.  *    acknowledgment:
  35.  *    "This product includes software developed by the Apache Group
  36.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  37.  *
  38.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  39.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  41.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  42.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  44.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  47.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  48.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  49.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  50.  * ====================================================================
  51.  *
  52.  * This software consists of voluntary contributions made by many
  53.  * individuals on behalf of the Apache Group and was originally based
  54.  * on public domain software written at the National Center for
  55.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  56.  * For more information on the Apache Group and the Apache HTTP server
  57.  * project, please see <http://www.apache.org/>.
  58.  *
  59.  */
  60.  
  61. /*
  62. **  Implementation of a Generic Hook Interface for Apache
  63. **  Written by Ralf S. Engelschall <rse@engelschall.com> 
  64. **
  65. **  See POD document at end of this file for description.
  66. **  View it with the command ``pod2man ap_hook.h | nroff -man | more''
  67. **
  68. **  Attention: This header file is a little bit tricky.
  69. **             It's a combination of a C source and an embedded POD document
  70. **             The purpose of this is to have both things together at one
  71. **             place. So you can both pass this file to the C compiler and 
  72. **             the pod2man translater.
  73. */
  74.  
  75. #ifdef EAPI
  76.  
  77. #ifndef AP_HOOK_H
  78. #define AP_HOOK_H
  79.  
  80. /*
  81.  * Function Signature Specification:
  82.  *
  83.  * We encode the complete signature ingredients as a bitfield
  84.  * stored in a single unsigned long integer value, which can be
  85.  * constructed with AP_HOOK_SIGx(...)
  86.  */
  87.  
  88. /* the type of the signature bitfield */
  89. typedef unsigned long int ap_hook_sig;
  90.  
  91. /* the mask (bin) 111 (hex 0x7) for the triples in the bitfield */
  92. #define AP_HOOK_SIG_TRIPLE_MASK  0x7
  93.  
  94. /* the position of the triple */
  95. #define AP_HOOK_SIG_TRIPLE_POS(n) ((n)*3)
  96.  
  97. /* the constructor for triple #n with value v */
  98. #define AP_HOOK_SIG_TRIPLE(n,v) \
  99.         (((ap_hook_sig)(v))<<((AP_HOOK_##n)*3))
  100.  
  101. /* the check whether triple #n in sig contains value v */
  102. #define AP_HOOK_SIG_HAS(sig,n,v) \
  103.         ((((ap_hook_sig)(sig))&AP_HOOK_SIG_TRIPLE(n, AP_HOOK_SIG_TRIPLE_MASK)) == (AP_HOOK_##n##_##v))
  104.  
  105. /* utility function to get triple #n in sig */
  106. #define AP_HOOK_SIG_TRIPLE_GET(sig,n) \
  107.         ((((ap_hook_sig)(sig))>>AP_HOOK_SIG_TRIPLE_POS(n))&(AP_HOOK_SIG_TRIPLE_MASK))
  108.  
  109. /* utility function to set triple #n in sig to value v */
  110. #define AP_HOOK_SIG_TRIPLE_SET(sig,n,v) \
  111.         ((((ap_hook_sig)(sig))&~(AP_HOOK_SIG_TRIPLE_MASK<<AP_HOOK_SIG_TRIPLE_POS(n)))|((v)<<AP_HOOK_SIG_TRIPLE_POS(n)))
  112.  
  113. /* define the ingredients for the triple #0: id stuff */
  114. #define AP_HOOK_ID          0
  115. #define AP_HOOK_ID_ok       AP_HOOK_SIG_TRIPLE(ID,0)
  116. #define AP_HOOK_ID_undef    AP_HOOK_SIG_TRIPLE(ID,1)
  117.  
  118. /* define the ingredients for the triple #1: return code */
  119. #define AP_HOOK_RC          1
  120. #define AP_HOOK_RC_void     AP_HOOK_SIG_TRIPLE(RC,0)
  121. #define AP_HOOK_RC_char     AP_HOOK_SIG_TRIPLE(RC,1)
  122. #define AP_HOOK_RC_int      AP_HOOK_SIG_TRIPLE(RC,2)
  123. #define AP_HOOK_RC_long     AP_HOOK_SIG_TRIPLE(RC,3)
  124. #define AP_HOOK_RC_float    AP_HOOK_SIG_TRIPLE(RC,4)
  125. #define AP_HOOK_RC_double   AP_HOOK_SIG_TRIPLE(RC,5)
  126. #define AP_HOOK_RC_ptr      AP_HOOK_SIG_TRIPLE(RC,6)
  127.  
  128. /* define the ingredients for the triple #2: argument 1 */
  129. #define AP_HOOK_A1          2
  130. #define AP_HOOK_A1_ctx      AP_HOOK_SIG_TRIPLE(A1,0)
  131. #define AP_HOOK_A1_char     AP_HOOK_SIG_TRIPLE(A1,1)
  132. #define AP_HOOK_A1_int      AP_HOOK_SIG_TRIPLE(A1,2)
  133. #define AP_HOOK_A1_long     AP_HOOK_SIG_TRIPLE(A1,3)
  134. #define AP_HOOK_A1_float    AP_HOOK_SIG_TRIPLE(A1,4)
  135. #define AP_HOOK_A1_double   AP_HOOK_SIG_TRIPLE(A1,5)
  136. #define AP_HOOK_A1_ptr      AP_HOOK_SIG_TRIPLE(A1,6)
  137.  
  138. /* define the ingredients for the triple #3: argument 2 */
  139. #define AP_HOOK_A2          3
  140. #define AP_HOOK_A2_ctx      AP_HOOK_SIG_TRIPLE(A2,0)
  141. #define AP_HOOK_A2_char     AP_HOOK_SIG_TRIPLE(A2,1)
  142. #define AP_HOOK_A2_int      AP_HOOK_SIG_TRIPLE(A2,2)
  143. #define AP_HOOK_A2_long     AP_HOOK_SIG_TRIPLE(A2,3)
  144. #define AP_HOOK_A2_float    AP_HOOK_SIG_TRIPLE(A2,4)
  145. #define AP_HOOK_A2_double   AP_HOOK_SIG_TRIPLE(A2,5)
  146. #define AP_HOOK_A2_ptr      AP_HOOK_SIG_TRIPLE(A2,6)
  147.  
  148. /* define the ingredients for the triple #4: argument 3 */
  149. #define AP_HOOK_A3          4
  150. #define AP_HOOK_A3_ctx      AP_HOOK_SIG_TRIPLE(A3,0)
  151. #define AP_HOOK_A3_char     AP_HOOK_SIG_TRIPLE(A3,1)
  152. #define AP_HOOK_A3_int      AP_HOOK_SIG_TRIPLE(A3,2)
  153. #define AP_HOOK_A3_long     AP_HOOK_SIG_TRIPLE(A3,3)
  154. #define AP_HOOK_A3_float    AP_HOOK_SIG_TRIPLE(A3,4)
  155. #define AP_HOOK_A3_double   AP_HOOK_SIG_TRIPLE(A3,5)
  156. #define AP_HOOK_A3_ptr      AP_HOOK_SIG_TRIPLE(A3,6)
  157.  
  158. /* define the ingredients for the triple #5: argument 4 */
  159. #define AP_HOOK_A4          5
  160. #define AP_HOOK_A4_ctx      AP_HOOK_SIG_TRIPLE(A4,0)
  161. #define AP_HOOK_A4_char     AP_HOOK_SIG_TRIPLE(A4,1)
  162. #define AP_HOOK_A4_int      AP_HOOK_SIG_TRIPLE(A4,2)
  163. #define AP_HOOK_A4_long     AP_HOOK_SIG_TRIPLE(A4,3)
  164. #define AP_HOOK_A4_float    AP_HOOK_SIG_TRIPLE(A4,4)
  165. #define AP_HOOK_A4_double   AP_HOOK_SIG_TRIPLE(A4,5)
  166. #define AP_HOOK_A4_ptr      AP_HOOK_SIG_TRIPLE(A4,6)
  167.  
  168. /* define the ingredients for the triple #6: argument 5 */
  169. #define AP_HOOK_A5          6
  170. #define AP_HOOK_A5_ctx      AP_HOOK_SIG_TRIPLE(A5,0)
  171. #define AP_HOOK_A5_char     AP_HOOK_SIG_TRIPLE(A5,1)
  172. #define AP_HOOK_A5_int      AP_HOOK_SIG_TRIPLE(A5,2)
  173. #define AP_HOOK_A5_long     AP_HOOK_SIG_TRIPLE(A5,3)
  174. #define AP_HOOK_A5_float    AP_HOOK_SIG_TRIPLE(A5,4)
  175. #define AP_HOOK_A5_double   AP_HOOK_SIG_TRIPLE(A5,5)
  176. #define AP_HOOK_A5_ptr      AP_HOOK_SIG_TRIPLE(A5,6)
  177.  
  178. /* define the ingredients for the triple #7: argument 6 */
  179. #define AP_HOOK_A6          7
  180. #define AP_HOOK_A6_ctx      AP_HOOK_SIG_TRIPLE(A6,0)
  181. #define AP_HOOK_A6_char     AP_HOOK_SIG_TRIPLE(A6,1)
  182. #define AP_HOOK_A6_int      AP_HOOK_SIG_TRIPLE(A6,2)
  183. #define AP_HOOK_A6_long     AP_HOOK_SIG_TRIPLE(A6,3)
  184. #define AP_HOOK_A6_float    AP_HOOK_SIG_TRIPLE(A6,4)
  185. #define AP_HOOK_A6_double   AP_HOOK_SIG_TRIPLE(A6,5)
  186. #define AP_HOOK_A6_ptr      AP_HOOK_SIG_TRIPLE(A6,6)
  187.  
  188. /* define the ingredients for the triple #8: argument 7 */
  189. #define AP_HOOK_A7          8
  190. #define AP_HOOK_A7_ctx      AP_HOOK_SIG_TRIPLE(A7,0)
  191. #define AP_HOOK_A7_char     AP_HOOK_SIG_TRIPLE(A7,1)
  192. #define AP_HOOK_A7_int      AP_HOOK_SIG_TRIPLE(A7,2)
  193. #define AP_HOOK_A7_long     AP_HOOK_SIG_TRIPLE(A7,3)
  194. #define AP_HOOK_A7_float    AP_HOOK_SIG_TRIPLE(A7,4)
  195. #define AP_HOOK_A7_double   AP_HOOK_SIG_TRIPLE(A7,5)
  196. #define AP_HOOK_A7_ptr      AP_HOOK_SIG_TRIPLE(A7,6)
  197.  
  198. /* define the ingredients for the triple #9: argument 8 */
  199. #define AP_HOOK_A8          9
  200. #define AP_HOOK_A8_ctx      AP_HOOK_SIG_TRIPLE(9,0)
  201. #define AP_HOOK_A8_char     AP_HOOK_SIG_TRIPLE(9,1)
  202. #define AP_HOOK_A8_int      AP_HOOK_SIG_TRIPLE(9,2)
  203. #define AP_HOOK_A8_long     AP_HOOK_SIG_TRIPLE(9,3)
  204. #define AP_HOOK_A8_float    AP_HOOK_SIG_TRIPLE(9,4)
  205. #define AP_HOOK_A8_double   AP_HOOK_SIG_TRIPLE(9,5)
  206. #define AP_HOOK_A8_ptr      AP_HOOK_SIG_TRIPLE(9,6)
  207.   
  208. /* the constructor for unknown signatures */
  209. #define AP_HOOK_SIG_UNKNOWN AP_HOOK_ID_undef
  210.  
  211. /* the constructor for signatures with 1 type */
  212. #define AP_HOOK_SIG1(rc) \
  213.         (AP_HOOK_RC_##rc)
  214.  
  215. /* the constructor for signatures with 2 types */
  216. #define AP_HOOK_SIG2(rc,a1) \
  217.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1)
  218.  
  219. /* the constructor for signatures with 3 types */
  220. #define AP_HOOK_SIG3(rc,a1,a2) \
  221.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2)
  222.  
  223. /* the constructor for signatures with 4 types */
  224. #define AP_HOOK_SIG4(rc,a1,a2,a3) \
  225.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3)
  226.  
  227. /* the constructor for signatures with 5 types */
  228. #define AP_HOOK_SIG5(rc,a1,a2,a3,a4) \
  229.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4)
  230.  
  231. /* the constructor for signatures with 6 types */
  232. #define AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5) \
  233.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5)
  234.  
  235. /* the constructor for signatures with 7 types */
  236. #define AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6) \
  237.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6)
  238.  
  239. /* the constructor for signatures with 8 types */
  240. #define AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7) \
  241.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7)
  242.  
  243. /* the constructor for signatures with 9 types */
  244. #define AP_HOOK_SIG9(rc,a1,a2,a3,a4,a5,a6,a7,a8) \
  245.         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7|AP_HOOK_A8_##a8)
  246.  
  247. /*
  248.  * Return Value Mode Identification
  249.  */
  250.  
  251. /* the type of the return value modes */
  252. typedef unsigned int ap_hook_mode;
  253.  
  254. /* the mode of the return value */
  255. #define AP_HOOK_MODE_UNKNOWN  0
  256. #define AP_HOOK_MODE_TOPMOST  1
  257. #define AP_HOOK_MODE_DECLINE  2
  258. #define AP_HOOK_MODE_DECLTMP  3
  259. #define AP_HOOK_MODE_ALL      4
  260.  
  261. /* the constructors for the return value modes */
  262. #define AP_HOOK_TOPMOST       AP_HOOK_MODE_TOPMOST
  263. #define AP_HOOK_DECLINE(val)  AP_HOOK_MODE_DECLINE, (val)   
  264. #define AP_HOOK_DECLTMP(val)  AP_HOOK_MODE_DECLTMP, (val)   
  265. #define AP_HOOK_ALL           AP_HOOK_MODE_ALL
  266.  
  267. /*
  268.  * Hook State Identification
  269.  */
  270.  
  271. /* the type of the hook state */
  272. typedef unsigned short int ap_hook_state;
  273.  
  274. /* the values of the hook state */
  275. #define AP_HOOK_STATE_UNDEF       0
  276. #define AP_HOOK_STATE_NOTEXISTANT 1
  277. #define AP_HOOK_STATE_ESTABLISHED 2
  278. #define AP_HOOK_STATE_CONFIGURED  3
  279. #define AP_HOOK_STATE_REGISTERED  4
  280.  
  281. /*
  282.  * Hook Context Identification
  283.  *
  284.  * Notice: Null is ok here, because AP_HOOK_NOCTX is just a dummy argument
  285.  *         because we know from the signature whether the argument is a
  286.  *         context value or just the dummy value.
  287.  */
  288.  
  289. #define AP_HOOK_NOCTX  (void *)(0)
  290. #define AP_HOOK_CTX(v) (void *)(v)
  291.  
  292. /*
  293.  * Internal Hook Record Definition
  294.  */
  295.  
  296. /* the union holding the arbitrary decline values */
  297. typedef union {
  298.     char   v_char;
  299.     int    v_int;
  300.     long   v_long;
  301.     float  v_float;
  302.     double v_double;
  303.     void  *v_ptr;
  304. } ap_hook_value;
  305.  
  306. /* the structure holding one hook function and its context */
  307. typedef struct {
  308.     void *hf_ptr;              /* function pointer       */
  309.     void *hf_ctx;              /* function context       */
  310. } ap_hook_func;
  311.  
  312. /* the structure holding one hook entry with all its registered functions */
  313. typedef struct {
  314.     char          *he_hook;    /* hook name (=unique id) */
  315.     ap_hook_sig    he_sig;     /* hook signature         */
  316.     int            he_modeid;  /* hook mode id           */
  317.     ap_hook_value  he_modeval; /* hook mode value        */
  318.     ap_hook_func **he_func;    /* hook registered funcs  */
  319. } ap_hook_entry;
  320.  
  321. /* the maximum number of hooks and functions per hook */
  322. #define AP_HOOK_MAX_ENTRIES 512
  323. #define AP_HOOK_MAX_FUNCS   128
  324.  
  325. /*
  326.  * Extended Variable Argument (vararg) Support
  327.  *
  328.  * In ANSI C varargs exists, but because the prototypes of function with
  329.  * varargs cannot reflect the types of the varargs, K&R argument passing
  330.  * conventions have to apply for the compiler.  This means mainly a conversion
  331.  * of shorter type variants to the maximum variant (according to sizeof). The
  332.  * above va_type() macro provides this mapping from the wanted types to the
  333.  * physically used ones.
  334.  */
  335.  
  336. /* the mapping */
  337. #define VA_TYPE_char   int
  338. #define VA_TYPE_short  int
  339. #define VA_TYPE_int    int
  340. #define VA_TYPE_long   long
  341. #define VA_TYPE_float  double
  342. #define VA_TYPE_double double
  343. #define VA_TYPE_ptr    void *
  344. #define VA_TYPE_ctx    void *
  345.  
  346. /* the constructor */
  347. #ifdef  va_type
  348. #undef  va_type
  349. #endif
  350. #define va_type(type)  VA_TYPE_ ## type
  351.  
  352. /*
  353.  * Miscellaneous stuff
  354.  */
  355.  
  356. #ifndef FALSE
  357. #define FALSE 0
  358. #define TRUE  !FALSE
  359. #endif
  360.  
  361. /*
  362.  * Wrapper macros for the callback-function register/unregister calls.  
  363.  * 
  364.  * Background: Strict ANSI C doesn't allow a function pointer to be treated as
  365.  * a void pointer on argument passing, but we cannot declare the argument as a
  366.  * function prototype, because the functions can have arbitrary signatures. So
  367.  * we have to use a void pointer here. But to not require explicit casts on
  368.  * function pointers for every register/unregister call, we smooth the API a
  369.  * little bit by providing these macros.
  370.  */
  371.  
  372. #define ap_hook_register(hook,func,ctx) ap_hook_register_I(hook,(void *)(func),ctx)
  373. #define ap_hook_unregister(hook,func)   ap_hook_unregister_I(hook,(void *)(func))
  374.  
  375. /*
  376.  * Prototypes for the hook API functions
  377.  */
  378.  
  379. API_EXPORT(void)          ap_hook_init         (void);
  380. API_EXPORT(void)          ap_hook_kill         (void);
  381. API_EXPORT(int)           ap_hook_configure    (char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...);
  382. API_EXPORT(int)           ap_hook_register_I   (char *hook, void *func, void *ctx);
  383. API_EXPORT(int)           ap_hook_unregister_I (char *hook, void *func);
  384. API_EXPORT(ap_hook_state) ap_hook_status       (char *hook);
  385. API_EXPORT(int)           ap_hook_use          (char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...);
  386. API_EXPORT(int)           ap_hook_call         (char *hook, ...);
  387.  
  388. #endif /* AP_HOOK_H */
  389.  
  390. #endif /* EAPI */
  391. /*
  392. =pod
  393. ##
  394. ##  Embedded POD document
  395. ##
  396.  
  397. =head1 NAME
  398.  
  399. B<ap_hook> - B<Generic Hook Interface for Apache>
  400.  
  401. =head1 SYNOPSIS
  402.  
  403. B<Hook Library Setup:>
  404.  
  405.  void ap_hook_init(void);
  406.  void ap_hook_kill(void);
  407.  
  408. B<Hook Configuration and Registration:>
  409.  
  410.  int ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode mode);
  411.  int ap_hook_register(char *hook, void *func, void *ctx);
  412.  int ap_hook_unregister(char *hook, void *func);
  413.  
  414. B<Hook Usage:>
  415.  
  416.  ap_hook_state ap_hook_status(char *hook);
  417.  int ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode mode, ...);
  418.  int ap_hook_call(char *hook, ...);
  419.  
  420. B<Hook Signature Constructors> (ap_hook_sig):
  421.  
  422.  AP_HOOK_SIG1(rc)
  423.  AP_HOOK_SIG2(rc,a1)
  424.  AP_HOOK_SIG3(rc,a1,a2)
  425.  AP_HOOK_SIG4(rc,a1,a2,a3)
  426.  AP_HOOK_SIG5(rc,a1,a2,a3,a4)
  427.  AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5)
  428.  AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6)
  429.  AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7)
  430.  
  431. B<Hook Modes Constructors> (ap_hook_mode):
  432.  
  433.  AP_HOOK_TOPMOST
  434.  AP_HOOK_DECLINE(value)
  435.  AP_HOOK_DECLTMP(value)
  436.  AP_HOOK_ALL
  437.  
  438. B<Hook States> (ap_hook_state):
  439.  
  440.  AP_HOOK_STATE_UNDEF
  441.  AP_HOOK_STATE_NOTEXISTANT
  442.  AP_HOOK_STATE_ESTABLISHED
  443.  AP_HOOK_STATE_CONFIGURED 
  444.  AP_HOOK_STATE_REGISTERED
  445.  
  446. =head1 DESCRIPTION
  447.  
  448. This library implements a generic hook interface for Apache which can be used
  449. to loosely couple code through arbitrary hooks. There are two use cases for
  450. this mechanism:
  451.  
  452. =over 3
  453.  
  454. =item B<1. Extension and Overrides>
  455.  
  456. Inside a specific code section you want to perform a specific function call
  457. for extension reasons.  But you want to allow one or more modules to implement
  458. this function by registering hooks. Those hooks are registered on a stack and
  459. can be even configured to have a I<decline> return value. As long as there are
  460. functions which return the decline value the next function on the stack is
  461. tried. When the first function doesn't return the decline value the hook call
  462. stops. 
  463.  
  464. The original intent of this use case is to provide a flexible extension
  465. mechanism where modules can override functionality.
  466.  
  467. =item B<2. Intercommunication>
  468.  
  469. Inside a specific code you have a function you want to export. But you first
  470. want to allow other code to override this function.  And second you want to
  471. export this function without real object file symbol references. Instead you
  472. want to register the function and let the users call this function by name. 
  473.  
  474. The original intent of this use case is to allow inter-module communication
  475. without direct symbol references, which are a big I<no-no> for the I<Dynamic
  476. Shared Object> (DSO) situation.
  477.  
  478. =back
  479.  
  480. And the following design goals existed:
  481.  
  482. =over 3
  483.  
  484. =item B<1. Minimum code changes>
  485.  
  486. The hook calls should look very similar to the corresponding direct function
  487. call to allow one to easily translate it. And the total amount of changes for
  488. the hook registration, hook configuration and hook usage should be as small as
  489. possible to minimize the total code changes. Additionally a shorthand API
  490. function (ap_hook_use) should be provided which lets one trivially add a hook
  491. by just changing the code at a single location.
  492.  
  493. =item B<2. The hook call has to be maximum flexible>
  494.  
  495. In order to avoid nasty hacks, maximum flexiblity for the hook calls is
  496. needed, i.e. any function signature (the set of types for the return value and
  497. the arguments) should be supported.  And it should be possible to
  498. register always a context (ctx) variable with a function which is passed to
  499. the corresponding function when the hook call is performed.
  500.  
  501. =back
  502.  
  503. The implementation of this library directly followed these two design goals.
  504.  
  505. =head1 USAGE
  506.  
  507. Using this hook API is a four-step process:
  508.  
  509. =over 3
  510.  
  511. =item B<1. Initialization>
  512.  
  513. Initialize or destroy the hook mechanism inside your application program:
  514.  
  515.  ap_hook_init();
  516.     :
  517.  ap_hook_kill();
  518.  
  519. =item B<2. Configuration>
  520.  
  521. Configure a particular hook by specifing its name, signature and return type
  522. semantic:
  523.  
  524.  ap_hook_configure("lookup", AP_HOOK_SIG2(ptr,ptr,ctx), AP_HOOK_DECLINE(NULL));
  525.  ap_hook_configure("setup", AP_HOOK_SIG2(int,ptr,char), AP_HOOK_DECLTMP(FALSE));
  526.  ap_hook_configure("read", AP_HOOK_SIG2(void,ptr), AP_HOOK_TOPMOST);
  527.  ap_hook_configure("logit", AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL);
  528.  
  529. This configures four hooks: 
  530.  
  531. A hook named C<lookup> with the signature C<void *lookup(void *, void *)>
  532. (where the second argument is C<NULL> or the private context pointer of the
  533. hook function which can be optionally provided at the registration step
  534. later) and a return code semantic which says: Proceed as long as the
  535. registered lookup functions return C<NULL> or no more registered functions
  536. exists. A call for this hook has to provide 2 argument only (a pointer to the
  537. return variable and the first argument), because the context is
  538. implicitly provided by the hook mechanism. Sample idea: I<The first function
  539. who was successful in looking up a variable provides the value>.
  540.  
  541. A hook named C<setup> with the signature C<int setup(void *, char)" and a
  542. return code semantic equal to the one of the C<lookup> hook. But the decline
  543. return value is implemented by a temporay variable of the hook mechanism and
  544. only used for the decline decision. So a call to this hook has to provide 2
  545. arguments only (the first and second argument, but no address to a return
  546. value). Sample idea: I<Any function can handle the setup and when one
  547. function handled it stops the processing by indicating this with the return
  548. value>.
  549.  
  550. A hook named C<read> with the signature C<void read(void *)> and a return code
  551. semantic which says: Only the top most function on the registered function
  552. stack is tried (and independet of a possible return value in non-void
  553. context). A call to this hook has to provide exactly 1 argument (the
  554. single argument to the hook function). Sample idea: I<We want to
  555. use a read function and allow others to override it, but independent how much
  556. registered functions exists, only top most (= last registered) function
  557. overrides and is used>.
  558.  
  559. A hook named C<logit> with the signature C<void logit(void *)> and a return
  560. code semantic which says: All registered functions on the hook functioin stack
  561. are tried. Sample idea: I<We pass a FILE pointer to the logging functions and
  562. any function can log whatever it wants>.
  563.  
  564. =item B<3. Registration>
  565.  
  566. Register the actual functions which should be used by the hook:
  567.  
  568.  ap_hook_register("lookup", mylookup, mycontext);
  569.  ap_hook_register("setup", mysetup);
  570.  ap_hook_register("read", myread);
  571.  ap_hook_register("logit", mylogit);
  572.  
  573. This registers the function C<mylookup()> under the C<lookup> hook with the
  574. private context given by the variable C<mycontext>. And it registers the
  575. function C<mysetup()> under the C<setup> hook without any context. Same for
  576. C<myread> and C<mylogit>.
  577.  
  578. =item B<4. Usage>
  579.  
  580. Finally use the hooks, i.e. instead of using direct function calls like
  581.         
  582.  rc = mylookup(a1, a2);
  583.  rc = mysetup(a1, a2);
  584.  myread(a1);
  585.  mylogit(a1);
  586.  
  587. you now use:
  588.  
  589.  ap_hook_call("lookup", &rc, a1, a2);
  590.  ap_hook_call("setup", &rc, a1, a2);
  591.  ap_hook_call("read", a1);
  592.  ap_hook_call("logit", a1);
  593.  
  594. which are internally translated to:
  595.  
  596.  rc = mylookup(a1, a2, mycontext);
  597.  rc = mysetup(a1, a2);
  598.  myread(a1);
  599.  mylogit(a1);
  600.  
  601. Notice two things here: First the context (C<mycontext>) for the C<mylookup()>
  602. function is automatically added by the hook mechanism. And it is a different
  603. (and not fixed) context for each registered function, of course.  Second,
  604. return values always have to be pushed into variables and a pointer to them
  605. has to be given as the second argument to C<ap_hook_call> (except for
  606. functions which have a void return type, of course).
  607.  
  608. BTW, the return value of C<ap_hook_call()> is always C<TRUE> or C<FALSE>.
  609. C<TRUE> when at least one function call was successful (always the case for
  610. C<AP_HOOK_TOPMOST> and C<AP_HOOK_ALL>). C<FALSE> when all functions
  611. returned the decline value or no functions are registered at all.
  612.  
  613. =back
  614.  
  615. =head1 RESTRICTIONS
  616.  
  617. To make the hook implementation efficient and to not bloat up the code too
  618. much a few restrictions have to make:
  619.  
  620. =over 3
  621.  
  622. =item 1.
  623.  
  624. Only function calls with up to 4 arguments are implemented. When more are
  625. needed you can either extend the hook implementation by using more bits for
  626. the signature configuration or you can do a workaround when the function is
  627. your own one: Put the remaining (N-4-1) arguments into a structure and pass
  628. only a pointer (one argument) as the forth argument.
  629.  
  630. =item 2.
  631.  
  632. Only the following ANSI C variable types are supported:
  633.  
  634.  - For the return value: 
  635.    void (= none), char, int, float, double, ptr (= void *)
  636.  - For the arguments:
  637.    ctx  (= context), char, int, float, double, ptr (= void *)
  638.  
  639. This means in theory that 6^5 (=7776) signature combinations are possible. But
  640. because we don't need all of them inside Apache and it would bloat up the code
  641. too dramatically we implement only a subset of those combinations. The
  642. implemented signatures can be specified inside C<ap_hook.c> and the
  643. corresponding code can be automatically generated by running ``C<perl
  644. ap_hook.c>'' (yeah, no joke ;-).  So when you need a hook with a different
  645. still not implemented signature you either have to again use a workaround as
  646. above (i.e. use a structure) or just add the signature to the C<ap_hook.c>
  647. file.
  648.  
  649. =head1 EXAMPLE
  650.  
  651. We want to call `C<ssize_t read(int, void *, size_t)>' through hooks in order
  652. to allow modules to override this call.  So, somewhere we have a replacement
  653. function for C<read()> defined (same signature, of course):
  654.  
  655.  ssize_t my_read(int, void *, size_t);
  656.  
  657. We now configure a C<read> hook. Here the C<AP_HOOK_SIGx()> macro defines the
  658. signature of the C<read()>-like callback functions and has to match the
  659. prototype of C<read()>. But we have to replace typedefs with the physical
  660. underlaying ANSI C types. And C<AP_HOOK_DECLINE()> sets the return value of
  661. the read()-like functions which forces the next hook to be called (here -1).
  662. And we register the original C<read()> function as the default hook.
  663.  
  664.  ap_hook_configure("read", 
  665.                    AP_HOOK_SIG4(int,int,ptr,int), 
  666.                    AP_HOOK_DECLINE(-1));
  667.  ap_hook_register("read", read);
  668.  
  669. Now a module wants to override the C<read()> call and registers the
  670. C<my_read()> function:
  671.  
  672.  ap_hook_register("read", my_read);
  673.  
  674. The function logically gets pushed onto a stack, so the execution order is the
  675. reverse registering order, i.e. I<last registered - first called>. Now we can
  676. replace the standard C<read()> call
  677.  
  678.  bytes = read(fd, buf, bufsize);
  679.  if (bytes == -1)
  680.     ...error...
  681.  
  682. with the hook based call:
  683.  
  684.   rc = ap_hook_call("read", &bytes, fd, buf, bufsize);
  685.   if (rc == FALSE)
  686.      ...error...
  687.  
  688. Now internally the following is done: The call `C<bytes = my_read(fd, buf,
  689. bufsize)>' is done. When it returns not -1 (the decline value) nothing
  690. more is done. But when C<my_read()> returns -1 the next function is tried:
  691. `C<bytes = read(fd, buf, bufsize)>'. When this one also returns -1 you get
  692. `rc == FALSE'. When it finally returns not -1 you get `rc == TRUE'.
  693.  
  694. =head1 SEE ALSO
  695.  
  696. ap_ctx(3)
  697.  
  698. =head1 HISTORY
  699.  
  700. The ap_hook(3) interface was originally designed and 
  701. implemented in October 1998 by Ralf S. Engelschall.
  702.  
  703. =head1 AUTHOR
  704.  
  705.  Ralf S. Engelschall
  706.  rse@engelschall.com
  707.  www.engelschall.com
  708.  
  709. =cut
  710. */
  711.